#include "IpcWrappers.h"

namespace SystemV
{
	int MsgQueue::create( key_t key, int flags /*= IPC_CREAT | 0666*/ )
	{
		msgid_ = msgget(key, flags);
		if (-1 == msgid_)
		{
			return -1;
		}

		return 0;
	}

	int MsgQueue::connect( key_t key )
	{
		msgid_ = msgget(key, 0);
		if (-1 == msgid_)
		{
			return -1;
		}
		return 0;
	}
	
	int MsgQueue::send( const char* msgbuf, int msgtype, int flags /*= IPC_NOWAIT*/ )
	{
		MsgBuf send_buf;
		send_buf.type_ = msgtype;
		memcpy(send_buf.msgbuf_, msgbuf, Max_Mq_Msg_Size);
		int ret = 0; 
		do
		{
			ret = msgsnd(msgid_, &send_buf, Max_Mq_Msg_Size, flags);
		}while ((-1 == ret) && (IPC_NOWAIT != (flags & IPC_NOWAIT)) && (EINTR == errno)); //如果在指定了阻塞的情况下，因为中断导致的发送失败，则需要重发
		
		return ret;
	}
	
	int MsgQueue::recv( void* msgp, long msgtype, int flags /*= 0*/ )
	{
        MsgBuf recv_buf;
		ssize_t size = 0;
		do
		{
			size = msgrcv(msgid_, &recv_buf, Max_Mq_Msg_Size, msgtype, flags);
		}while ((-1 == size) && (IPC_NOWAIT != (flags & IPC_NOWAIT)) && (EINTR == errno));
		memcpy(msgp, recv_buf.msgbuf_, size);
		return static_cast<int>(size);
	}
	
	int MsgQueue::remove( key_t key)
	{
		return msgctl(msgid_, key, 0);
	}

    int ShareMemory::create( key_t key, size_t size, int shmflg /*= IPC_CREAT|0666*/)
    {
        shmid_ = shmget(key, size, IPC_EXCL | shmflg);
        //创建失败
        if (-1 == shmid_)
        {
            //共享内存已经存在
            if (EEXIST == errno)
            {
                shmid_ = shmget(key, 0, 0);
                head_addr_ = (char*)shmat(shmid_, 0, 0);
                if ((char*)-1 == head_addr_)
                {
                    return -1;
                }

                return 0;
            }
            else
            {
                return -1;
            }
        }
       
        head_addr_ = (char*)shmat(shmid_, 0, 0);
        if ((char*)-1 == head_addr_)
        {
            return -1;
        }
        //初始化新创建的共享内存
        memset(head_addr_, 0, size);
        return 0;
    }


    int ShareMemory::connect( key_t key )
    {
        shmid_ = shmget(key, 0, 0);
        if (-1 == shmid_)
        {
            return -1;
        }
        head_addr_ = (char*)shmat(shmid_, 0, 0);
        if ((char*)-1 == head_addr_)
        {
            return -1;
        }

        return 0;
    }


    int ShareMemory::remove()
    {
        return shmctl(shmid_, IPC_RMID, NULL);
    }


    char* ShareMemory::get_addr()
    {
        return head_addr_;
    }

}   

Pipe::Pipe()
{
    fd[0] = -1;
    fd[1] = -1;
}

Pipe::~Pipe()
{
    close(fd[0]);
    close(fd[1]);
}


int Pipe::create()
{
    return pipe(fd);
}


int Pipe::send( void* buf, size_t len )
{
    return write(fd[1], buf, len);
}


int Pipe::recv( void* buf, size_t len )
{
    return read(fd[0], buf, len);
}
